<script>
  $(window).on('load', function () {
    $('.selectpicker').selectpicker({'selectedText': 'cat'});
    $('.selectpicker').selectpicker('refresh');
    $('.selectpicker').selectpicker('render');
  });
  $(function () {

    var appId = document.getElementById('appId').value;

    $('.selectpicker').selectpicker();

    var slaveIp_select = document.getElementById('slaveIp');
    $("div[name='addSlave-modal']").on('shown.bs.modal', function () {
      var addSlaveModal_id = $(this).attr('id');
      var instanceId = addSlaveModal_id.split('_')[1];

      if (document.getElementById('slaveIp' + instanceId).options.length == 0) {
        for (var i = 0; i < slaveIp_select.options.length; i++) {
          var text = slaveIp_select.options[i].text;
          var value = slaveIp_select.options[i].value;
          $('#slaveIp' + instanceId).append("<option value='" + value + "'>" + text + "</option>");
        }

        $('#slaveIp' + instanceId).selectpicker('refresh');
        $('#slaveIp' + instanceId).selectpicker('render');

        $('.dropdown-toggle').on('click',function(){
          $('.dropdown-toggle').dropdown();
        });
      }
    });

    $("div[name='addConfig-modal']").on('shown.bs.modal', function () {
      var addConfigModal_id = $(this).attr('id');
      var instanceId = addConfigModal_id.split('_')[1];
      $.post('${request.contextPath}/admin/app/redisConfig',
              {
                appId: appId,
                instanceId: instanceId
              },
              function (data) {
                var status = data.status;
                if (status == 1) {
                  var redisConfigMap = data.redisConfigMap;
                  $('#appConfigKey' + instanceId).append("<option value=''>" + '请选择' + "</option>");
                  for (var key in redisConfigMap) {
                    var item = '配置项：' + key + " | 配置值：" + redisConfigMap[key];
                    $('#appConfigKey' + instanceId).append("<option value='" + key + "'>" + item + "</option>");
                  }
                  $('#appConfigKey' + instanceId).selectpicker('refresh');
                  $('#appConfigKey' + instanceId).selectpicker('render');

                  $('.dropdown-toggle').on('click', function () {
                    $('.dropdown-toggle').dropdown();
                  });
                }
              }
      );
    });

    $("div[name='configAndRestart-modal']").on('shown.bs.modal', function () {
      var instanceId;
      var masterIds = document.getElementsByName(`selectOneMaster`);
      if(masterIds != undefined && masterIds.length != undefined && masterIds.length != null){
        for (var key of masterIds) {
          instanceId = masterIds[0].value;
          break;
        }
      }
      if(!(instanceId > 0)){
        alert("未能获取配置列表，请手动填写！");
        return false;
      }
      $.post('${request.contextPath}/admin/app/redisConfig',
              {
                appId: appId,
                instanceId: instanceId
              },
              function (data) {
                var status = data.status;
                if (status == 1) {
                  var redisConfigMap = data.redisConfigMap;
                  $('#configListId').append("<option value=''>" + '请选择' + "</option>");
                  for (var key in redisConfigMap) {
                    var item = '配置项：' + key + " | 配置值：" + redisConfigMap[key];
                    $('#configListId').append("<option value='" + key + "'>" + item + "</option>");
                  }
                  $('#configListId').selectpicker('refresh');
                  $('#configListId').selectpicker('render');

                  $('.dropdown-toggle').on('click', function () {
                    $('.dropdown-toggle').dropdown();
                  });
                }
              }
      );
    });

    $("div[name='configCommand-modal']").on('shown.bs.modal', function () {
      var instanceId;
      var masterIds = document.getElementsByName(`selectOneMaster`);
      if(masterIds != undefined && masterIds.length != undefined && masterIds.length != null){
        for (var key of masterIds) {
          instanceId = masterIds[0].value;
          break;
        }
      }
      if(!(instanceId > 0)){
        alert("未能获取命令列表，请确认！");
        return false;
      }
      //清空
      document.getElementById('cmdListId').options.length = 0;
      $('#cmdListId').selectpicker('destroy');
      $('#cmdListId').selectpicker();
      $('#existCommandName').html("");
      $('#commandName').html("");

      $.post('${request.contextPath}/admin/app/redisCommand',
              {
                appId: appId,
                instanceId: instanceId
              },
              function (data) {
                var status = data.status;
                if (status == 1) {
                  var commandList = data.commandList;
                  var cmdListHtml = "<option value=''>" + '请选择' + "</option>";

                  // 获取重命名配置，并更新已选
                  getRenameCommand(appId, instanceId).then(existCmdSet => {
                    for (var index in commandList) {
                      cmdListHtml += "<option id='" + commandList[index] + "'";
                      if(existCmdSet != undefined && existCmdSet.has(commandList[index])){
                        cmdListHtml += " selected ";
                      }
                      cmdListHtml += ">" + commandList[index] + "</option>";
                    }
                    $('#cmdListId').selectpicker('destroy');
                    $('#cmdListId').append(cmdListHtml);
                    $('#cmdListId').selectpicker();

                    setSelectedRenameCmd();
                    $('.dropdown-toggle').on('click', function () {
                      $('.dropdown-toggle').dropdown();
                    });
                  })
                  .catch(error => {
                    alert(error); // 打印错误信息
                    for (var index in commandList) {
                      cmdListHtml += "<option id='" + commandList[index] + "'";
                      cmdListHtml += ">" + commandList[index] + "</option>";
                    }
                    $('#cmdListId').selectpicker('destroy');
                    $('#cmdListId').append(cmdListHtml);
                    $('#cmdListId').selectpicker();
                    $('.dropdown-toggle').on('click', function () {
                      $('.dropdown-toggle').dropdown();
                    });
                  });
                }
              }
      );
    });

    $(function () { $("[data-bs-toggle='tooltip']").tooltip(); });

    {
      var search = window.location.search;
      var appId = getSearchString("appId", search);
      var configName = getSearchString("configName", search);
      var expectValue = getSearchString("expectValue", search);
      var instanceIds = getSearchString("instanceIds", search);
      if(appId != null && configName != null && instanceIds != null) {
        document.getElementById("configRestartId").click();
        $('#configAndRestartModal input[name="isUpdateConfig"][value="1"]').prop("checked", "checked");
        moduleSelect('1');
        document.getElementById("configName").value = configName;
        var configValues = document.getElementsByName("configValue");
        configValues[0].value = expectValue;
        var instanceSelect = document.getElementById("configInstanceList");
        var instanceIdStrs = instanceIds.split(",");
        $('#configInstanceList').selectpicker('val', instanceIdStrs);
        $('#configInstancneList').selectpicker('refresh');

        var transferSelect = document.getElementById("msTransferFlag");
        for(var i = 0; i < transferSelect.options.length; i++){
          if(transferSelect.options[i].value == 0){
            transferSelect.options[i].selected = true;
          }else{
            transferSelect.options[i].selected = false;
          }
        }
      }
    }
  })

  function getRenameCommand(appId, instanceId){
   return new Promise((resolve, reject) => {
    $.post('${request.contextPath}/admin/app/redisRenameCommand',
          {
            appId: appId,
            instanceId: instanceId
          },
          function (data) {
            var status = data.status;
            var commandSet = new Set();
            if (status == 1) {
              var renameCommands = data.renameCommands;
              var renameCmdHtml = "";
              for (var index in renameCommands) {
                renameCmdHtml += renameCommands[index].value + "\n";
                var cmdConfig = renameCommands[index].value;
                commandSet.add(cmdConfig.substring(0, cmdConfig.indexOf(" ")).trim());
              }
              $('#existCommandName').html(renameCmdHtml);
              resolve(commandSet);
            } else {
              reject("未获取到已有重命名命令，请确认");
            }
          }
      );
      });
  }
</script>

<script>
  // key(需要检索的键） url（传入的需要分割的url地址，例：?id=2&age=18）
  function getSearchString(key, Url) {
      var str = Url;
      str = str.substring(1, str.length); // 获取URL中?之后的字符（去掉第一位的问号）
      // 以&分隔字符串，获得类似name=xiaoli这样的元素数组
      var arr = str.split("&");
      var obj = new Object();
      // 将每一个数组元素以=分隔并赋给obj对象
      for (var i = 0; i < arr.length; i++) {
          var tmp_arr = arr[i].split("=");
          obj[decodeURIComponent(tmp_arr[0])] = decodeURIComponent(tmp_arr[1]);
      }
      return obj[key];
  }

  function setSelectedConfig(){
      var configName = $('#configListId option:selected').val();
      var configItem = $('#configListId option:selected').text();
      var splitStr = configItem.split("配置值：");
      var expectValue = splitStr[1];
      if(configName != null){
          document.getElementById("configName").value = configName;
          var configValues = document.getElementsByName("configValue");
          configValues[0].value = expectValue;
      }
  }

  function setSelectedRenameCmd(){
    var newCommandHtml = "";
    $('#cmdListId option:selected').each(function(){
      if($(this).val() != null){
        newCommandHtml += $(this).val() + "\n";
      }
    });
    document.getElementById("commandName").value = newCommandHtml;
  }

  function startInstance(appId, instanceId) {
      if (confirm("确认要开启" + instanceId + "实例吗?")) {
          $.ajax({
              type: "get",
              url: "${request.contextPath}/manage/instance/startInstance.json",
              data:
                  {
                      appId: appId,
                      instanceId: instanceId
                  },
              success: function (result) {
                  if (result.success == 1) {
                      alert("开启成功!");
                  } else {
                      alert("开启失败, msg: " + result.message);
                  }
                  window.location.reload();
              }
          });
      }
  }

  function shutdownInstance(appId, instanceId) {
      if (confirm("确认要下线" + instanceId + "实例吗?")) {
          $.ajax({
              type: "get",
              url: "${request.contextPath}/manage/instance/shutdownInstance.json",
              data:
                  {
                      appId: appId,
                      instanceId: instanceId
                  },
              success: function (result) {
                  if (result.success == 1) {
                      alert("关闭成功!");
                  } else {
                      alert("关闭失败, msg: " + result.message);
                  }
                  window.location.reload();
              }
          });
      }
  }

  function addConfigInstance(appId, instanceId, host, port) {
      var configKey = $('#appConfigKey' + instanceId).selectpicker('val');
      var newConfigKey = document.getElementById("newConfigKey" + instanceId).value;
      var configVal = document.getElementById("appConfigValue" + instanceId).value;

      if (newConfigKey == "") {
          if (configKey == "") {
              alert("配置项不能为空");
              return false;
          }
      } else {
          configKey = newConfigKey;
      }

      if (confirm("确认更新实例" + instanceId + "的配置: " + configKey + ":" + configVal)) {


          $.post("${request.contextPath}/manage/instance/addInstanceConfigChange",
              {
                  appId: appId,
                  host: host,
                  port: port,
                  instanceConfigKey: configKey,
                  instanceConfigValue: configVal
              },
              function (data) {
                  if (data.result == 1) {
                      alert("配置更新成功!");
                      window.location.reload();
                  } else {
                      alert("配置更新失败...");
                  }
              });
      }
  }

  function forgetInstance(appId, instanceId) {
      if (confirm("确认要永久下线" + instanceId + "实例吗?")) {
          $.ajax({
              type: "get",
              url: "${request.contextPath}/manage/instance/forgetInstance.json",
              data:
                  {
                      appId: appId,
                      instanceId: instanceId
                  },
              success: function (result) {
                  if (result.success == 1) {
                      alert("关闭成功!");
                  } else {
                      alert("关闭失败, msg: " + result.message);
                  }
                  window.location.reload();
              }
          });
      }
  }


  function redisClusterFailOverManual(appId, instanceId) {
      var redisClusterFailOverManualBtn = document.getElementById("redisClusterFailOverManualBtn" + instanceId);
      redisClusterFailOverManualBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/clusterSlaveFailOver',
          {
              appId: appId,
              slaveInstanceId: instanceId,
              failoverParam: ''
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisClusterFailOverManualInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisClusterFailOverManualModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisClusterFailOverManualBtn.disabled = false;
                  $("#redisClusterFailOverManualInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisClusterFailOverForce(appId, instanceId) {
      var redisClusterFailOverForceBtn = document.getElementById("redisClusterFailOverForceBtn" + instanceId);
      redisClusterFailOverForceBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/clusterSlaveFailOver',
          {
              appId: appId,
              slaveInstanceId: instanceId,
              failoverParam: 'force'
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisClusterFailOverForceInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisClusterFailOverForceModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisClusterFailOverForceBtn.disabled = false;
                  $("#redisClusterFailOverForceInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisClusterFailOverTakeOver(appId, instanceId) {
      var redisClusterFailOverTakeOverBtn = document.getElementById("redisClusterFailOverTakeOverBtn" + instanceId);
      redisClusterFailOverTakeOverBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/clusterSlaveFailOver',
          {
              appId: appId,
              slaveInstanceId: instanceId,
              failoverParam: 'takeover'
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisClusterFailOverTakeOverInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisClusterFailOverTakeOverModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisClusterFailOverTakeOverBtn.disabled = false;
                  $("#redisClusterFailOverTakeOverInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisClusterDelNode(appId, instanceId) {
      var redisClusterDelNodeBtn = document.getElementById("redisClusterDelNodeBtn" + instanceId);
      redisClusterDelNodeBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/clusterDelNode.json',
          {
              appId: appId,
              delNodeInstanceId: instanceId,
          },
          function (data) {
              var success = data.success;
              var message = data.message;
              if (success == 1) {
                  alert("执行成功!");
                  $("#redisClusterDelNodeInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisClusterDelNodeModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  alert(message);
                  redisClusterDelNodeBtn.disabled = false;
                  $("#redisClusterDelNodeInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function genSlaveIp(appId, instanceId) {
      var genSlaveIpNote = document.getElementById('genSlaveIpNote' + instanceId);
      genSlaveIpNote.style.display = 'none';
      $.post(
          '${request.contextPath}/manage/app/genSlaveIp',
          {
              appId: appId,
              masterInstanceId: instanceId
          },
          function (data) {
              var result = data.result;
              var ip = data.machineRes;
              if (result != 'success') {
                  genSlaveIpNote.innerHTML = '自动生成slave节点ip失败: ' + result;
                  genSlaveIpNote.style.display = '';
              } else {
                  console.log(ip);
                  $('#slaveIp' + instanceId).selectpicker('val', ip);
                  $('#slaveIp' + instanceId).selectpicker('refresh');
                  console.log($('#slaveIp' + instanceId).selectpicker('val'));
                  if ($('#slaveIp' + instanceId).selectpicker('val') == '-1') {
                      genSlaveIpNote.innerHTML = '自动生成slave节点ip失败，请重试';
                      genSlaveIpNote.style.display = '';
                  }
              }
          }
      );
  }


  function redisClusterAddSlave(appId, instanceId) {
      var slaveIpObj = document.getElementById("slaveIp" + instanceId);
      var index = slaveIpObj.selectedIndex;
      var slaveIp = slaveIpObj[index].value;
      if (slaveIp == "" || slaveIp == "-1") {
          alert("从节点Ip不能为空");
          return false;
      }
      var redisClusterAddSlaveBtn = document.getElementById("redisClusterAddSlaveBtn" + instanceId);
      redisClusterAddSlaveBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/addSlave',
          {
              appId: appId,
              masterInstanceId: instanceId,
              slaveHost: slaveIp
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisClusterAddSlaveInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>添加成功!<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisClusterAddSlaveModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisClusterAddSlaveBtn.disabled = false;
                  $("#redisClusterAddSlaveInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisSentinelAddSlave(appId, instanceId) {
      var slaveIp = document.getElementById("sentinelSlaveIp" + instanceId);
      if (slaveIp.value == "") {
          alert("从节点Ip不能为空");
          slaveIp.focus();
          return false;
      }
      var redisSentinelAddSlaveBtn = document.getElementById("redisSentinelAddSlaveBtn" + instanceId);
      redisSentinelAddSlaveBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/addSlave',
          {
              appId: appId,
              masterInstanceId: instanceId,
              slaveHost: slaveIp.value
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisSentinelAddSlaveInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>添加成功!<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisSentinelAddSlaveModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisSentinelAddSlaveBtn.disabled = false;
                  $("#redisSentinelAddSlaveInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }


  function redisSentinelFailOver(appId) {
      var redisSentinelFailOverBtn = document.getElementById("redisSentinelFailOverBtn");
      redisSentinelFailOverBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/sentinelFailOver',
          {
              appId: appId
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisSentinelFailOverInfo").html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisSentinelFailOverModal";
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisSentinelFailOverBtn.disabled = false;
                  $("#redisSentinelFailOverInfo").html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisSentinelReset(appId) {
      var redisSentinelFailOverBtn = document.getElementById("redisSentinelResetBtn");
      redisSentinelFailOverBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/sentinelReset',
          {
              appId: appId
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisSentinelResetInfo").html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisSentinelResetModal";
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisSentinelFailOverBtn.disabled = false;
                  $("#redisSentinelResetInfo").html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisAddFailSlotsMaster(appId, instanceId) {
      var failSlotsMasterHost = document.getElementById("failSlotsMasterHost" + instanceId);
      var redisAddFailSlotsMasterBtn = document.getElementById("redisAddFailSlotsMasterBtn" + instanceId);
      redisAddFailSlotsMasterBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/addFailSlotsMaster',
          {
              appId: appId,
              failSlotsMasterHost: failSlotsMasterHost.value,
              instanceId: instanceId
          },
          function (data) {
              if (data == 1 || data == 2) {
                  if (data == 1) {
                      alert("执行成功!");
                  } else {
                      alert("集群所有slots已经分配，无需补充！");
                  }
                  $("#redisAddFailSlotsMasterInfo" + instanceId).html("<div class='alert alert-error' ><strong>Success!</strong>执行成功，应用的拓扑结构要1分钟之后生效，请耐心等待<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisAddFailSlotsMasterModal" + instanceId;
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisAddFailSlotsMasterBtn.disabled = false;
                  $("#redisAddFailSlotsMasterInfo" + instanceId).html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function redisAddSentinel(appId) {
      var sentinelIp = document.getElementById("sentinelIp");
      if (sentinelIp.value == "") {
          alert("sentinel Ip不能为空");
          slaveIp.focus();
          return false;
      }
      var redisAddSentinelBtn = document.getElementById("redisAddSentinelBtn");
      redisAddSentinelBtn.disabled = true;
      $.post(
          '${request.contextPath}/manage/app/addSentinel',
          {
              appId: appId,
              sentinelHost: sentinelIp.value
          },
          function (data) {
              if (data == 1) {
                  alert("执行成功!");
                  $("#redisAddSentinelInfo").html("<div class='alert alert-error' ><strong>Success!</strong>添加成功!<button class='close' data-bs-dismiss='alert'></button></div>");
                  var targetId = "#redisAddSentinelModal";
                  setTimeout("$('" + targetId + "').modal('hide');window.location.reload();", 1000);
              } else {
                  redisAddSentinelBtn.disabled = false;
                  $("#redisAddSentinelInfo").html("<div class='alert alert-error' ><strong>Error!</strong>执行失败，请查找原因！<button class='close' data-bs-dismiss='alert'></button></div>");
              }
          }
      );
  }

  function moduleSelect(radioVal){
      if(radioVal == '0'){
          $("#moduleInfo").attr("style","display:none");
      }
      if(radioVal == '1'){
          $("#moduleInfo").attr("style","display:display");
      }
  }

  function addConfigRow(){
      var ul = document.getElementById("configRowGroup");
      var lis = document.getElementsByName(`configRow`);
      var li = lis[0].cloneNode(true);
      li.getElementsByTagName('input')[0].value="";
      ul.appendChild(li);
  }

  function config(appId) {
      var configList = null;
      var configInstanceList = null;
      var isUpdateConfig = $('input:radio[name="isUpdateConfig"]:checked').val();
      var tipInfo = "滚动重启";
      if(isUpdateConfig == 1){
          var configName = document.getElementById("configName").value;
          if(configName == null || configName == ""){
              alert("请填写配置项");
              return false;
          }
          var configValues = document.getElementsByName("configValue");
          configList = [];
          var newConfigValue = [];
          for(i = 0; i < configValues.length; i++){
              configList.push({
                  configName: configName,
                  configValue: configValues[i].value
              });
              newConfigValue.push(configValues[i].value);
          }
          if(configList.length < 1){
              alert("请至少填写一个配置值");
              return false;
          }
          configInstanceList = [];
          $('#configInstanceList option:selected').each(function(){
              if($(this).val() != null){
                  configInstanceList.push($(this).val());
              }
          });
          if(configInstanceList.length == 0){
              alert("请选择实例");
              return false;
          }

          tipInfo = "修改配置" + configName + "的值为：" + newConfigValue;
      }
      var msTransferFlag = document.getElementById("msTransferFlag").value;
      var data = {
          appId: appId,
          configFlag: isUpdateConfig == 1,
          transferFlag: msTransferFlag == 1,
          instanceList: configInstanceList,
          configList: configList
      };
      if (confirm("确认" + tipInfo)) {
          document.getElementById("configAndRestartCloseBtn").disabled = 'true';
          document.getElementById("configAndRestartBtn").disabled = 'true';
          document.getElementById("msTransferFlag").disabled = false;
          document.getElementById("configInstanceList").disabled = false;
          document.getElementById("addConfigRowBtn").disabled = false;
          $("#configAndRestartModal").find("input[type='radio']").attr("disabled", "disabled");
          $("#configAndRestartModal").find("input[type='text']").attr("disabled", "disabled");
          $.ajax({
              type: 'post',
              url:'${request.contextPath}/manage/app/restart/updateConfig',
              contentType:'application/json',
              data: JSON.stringify(data),
              dataType:'json',
              success:function (data) {
                  if (data.status == 200) {
                      if(data.data.commandSet == true){
                          alert("配置更新成功!");
                          window.location.href = "${request.contextPath}/manage/app/index?appId=" + appId;
                      }else{
                          alert("请点击重启，激活配置!");
                          document.getElementById("recordId").value = data.data.recordId;
                          document.getElementById("restartAfterConfigBtn").style.display = 'inline';
                          document.getElementById("configAndRestartCloseBtn").disabled = 'true';
                          document.getElementById("configAndRestartBtn").disabled = 'true';
                      }
                  } else {
                      alert("配置更新失败，请人工确认 : " + data.error);
                      document.getElementById("msTransferFlag").disabled = 'true';
                      document.getElementById("configInstanceList").disabled = 'true';
                      document.getElementById("addConfigRowBtn").disabled = 'true';
                      $("#configAndRestartModal").find("input[type='radio']").removeAttr("disabled");
                      $("#configAndRestartModal").find("input[type='text']").removeAttr("disabled");
                      document.getElementById("configAndRestartCloseBtn").disabled = false;
                      document.getElementById("configAndRestartBtn").disabled = false;
                  }
              }
          });
      }
  }

  function restart(appId) {
      var configList = null;
      var configInstanceList = null;
      var isUpdateConfig = $('input:radio[name="isUpdateConfig"]:checked').val();
      var tipInfo = "滚动重启";
      if(isUpdateConfig == 1){
          var configName = document.getElementById("configName").value;
          if(configName == null || configName == ""){
              alert("请填写配置项");
              return false;
          }
          var configValues = document.getElementsByName("configValue");
          configList = [];
          for(i = 0; i < configValues.length; i++){
              console.log(configValues[i].value);
              configList.push({
                  configName: configName,
                  configValue: configValues[i].value
              });
          }

          if(configList.length < 1){
              alert("请至少填写一个配置值");
              return false;
          }
          configInstanceList = [];
          $('#configInstanceList option:selected').each(function(){
              if($(this).val() != null){
                  configInstanceList.push($(this).val());
              }
          });
          if(configInstanceList.length == 0){
              alert("请选择实例");
              return false;
          }
          tipInfo = "修改配置" + configName + "并更新";
      }
      var msTransferFlag = document.getElementById("msTransferFlag").value;
      var msQuickFinishFlag = document.getElementById("msQuickFinishFlag").value;
      var recordId = document.getElementById("recordId").value;
      var data = {
          appId: appId,
          recordId: recordId,
          configFlag: isUpdateConfig == 1,
          transferFlag: msTransferFlag == 1,
          quickFinishFlag: msQuickFinishFlag == 1,
          instanceList: configInstanceList,
          configList: configList
      };
      if (confirm("确认" + tipInfo)) {
          document.getElementById("configAndRestartCloseBtn").disabled = 'true';
          document.getElementById("configAndRestartBtn").disabled = 'true';
          $.ajax({
              type: 'post',
              url:'${request.contextPath}/manage/app/restart/scrollRestart',
              contentType:'application/json',
              data: JSON.stringify(data),
              dataType:'json',
              success:function (data) {
                  if (data.status == 200) {
                      alert(data.data);
                      window.location.reload();
                  } else {
                      alert("重启失败，请确认 : " + data.error);
                  }
                  document.getElementById("configAndRestartCloseBtn").disabled = false;
                  document.getElementById("configAndRestartBtn").disabled = false;
              }
          });
      }else{
          document.getElementById("configAndRestartBtn").disabled = false;
      }
  }

  function configAndRestart(appId) {
      var isUpdateConfig = $('input:radio[name="isUpdateConfig"]:checked').val();
      if(isUpdateConfig == 1){
          return config(appId);
      }
      return restart(appId);
  }

  function configAndRestartClose(appId) {
      window.location.href = "${request.contextPath}/manage/app/index?appId=" + appId;
  }

    function configCommandClose(appId) {
      window.location.href = "${request.contextPath}/manage/app/index?appId=" + appId;
  }

  function openRestartRecord(appId){
      window.open("${request.contextPath}/manage/instance/opsList?tabId=3&appId=" + appId + "&pageNo=1");
      return;
  }

  function configCommand(appId) {
    var configList = null;
    var configInstanceList = null;
    var configName = "rename-command";
    var cmdSuffix = document.getElementById("commandSuffix").value;
    var commandSet = new Set();

    var newRenameCommands = document.getElementById("commandName").value;
    var newCmds = newRenameCommands.split("\n");
    for(i = 0; i < newCmds.length; i++){
      commandSet.add(newCmds[i]);
    }

    // var existRenameCommands = document.getElementById("existCommandName").value;
    // var existsCmdConfigs = existRenameCommands.split("\n");
    // for(i = 0; i < existsCmdConfigs.length; i++){
      // var cmdConfig = existsCmdConfigs[i];
      // commandSet.add(cmdConfig.substring(0, cmdConfig.indexOf(" ")).trim());
    // }

    configList = [];
    var newConfigValue = [];
    for(var command of commandSet){
      if(command != null && command != ''){
        configList.push({
            configName: configName,
            configValue: command + " " + (command + cmdSuffix)
        });
        newConfigValue.push(command + " " + (command + cmdSuffix));
      }
    }
    if(configList.length < 1){
      if (!confirm("确认清空命令重命名？")) {
        return;
      }
      configList.push({
            configName: configName,
            configValue: ""
        });
    }
    configInstanceList = [];
    $('#cmdInstanceList option:selected').each(function(){
        if($(this).val() != null){
            configInstanceList.push($(this).val());
        }
    });
    if(configInstanceList.length == 0){
        alert("请选择实例");
        return false;
    }

    tipInfo = "重命名命令" + configName + "的值为：" + newConfigValue;
    var data = {
        appId: appId,
        configFlag: true,
        transferFlag: false,
        instanceList: configInstanceList,
        configList: configList
    };
    if (confirm("确认" + tipInfo)) {
        document.getElementById("configCommandCloseBtn").disabled = 'true';
        document.getElementById("configCommandBtn").disabled = 'true';
        document.getElementById("cmdInstanceList").disabled = false;
        $("#configCommandModal").find("input[type='radio']").attr("disabled", "disabled");
        $("#configCommandModal").find("input[type='text']").attr("disabled", "disabled");
        $.ajax({
            type: 'post',
            url:'${request.contextPath}/manage/app/restart/updateConfig',
            contentType:'application/json',
            data: JSON.stringify(data),
            dataType:'json',
            success:function (data) {
                if (data.status == 200) {
                    if(data.data.commandSet == true){
                        alert("配置更新成功!");
                        window.location.href = "${request.contextPath}/manage/app/index?appId=" + appId;
                    }else{
                        alert("请点击重启，激活配置!");
                        document.getElementById("configCommandCloseBtn").disabled = 'true';
                        document.getElementById("configCommandBtn").disabled = 'true';
                    }
                } else {
                    alert("配置更新失败，请人工确认 : " + data.error);
                    document.getElementById("cmdInstanceList").disabled = 'true';
                    $("#configCommandModal").find("input[type='radio']").removeAttr("disabled");
                    $("#configCommandModal").find("input[type='text']").removeAttr("disabled");
                    document.getElementById("configCommandCloseBtn").disabled = false;
                    document.getElementById("configCommandBtn").disabled = false;
                }
            }
        });
      }
  }
</script>
<div class="row">
  <div class="col-12">
      <div class="card">
        <div class="card-header">
          <h4 class="card-title">
            应用实例管理-
            <a href="${request.contextPath}/admin/app/index?appId=${appDesc.appId!}" target="_blank">
              ${appDesc.name!}
            </a>
            (${appDesc.typeDesc!})
            <input type="hidden" id="appId" value="${appDesc.appId!}"/>
            <#if (appDesc.type == 2)>
              <#if lossSlotsSegmentMap?? && (lossSlotsSegmentMap?size > 0)>
                <font color="red">
                  丢失的slots:[
                  <#list lossSlotsSegmentMap?keys as key>
                    ${key!}-${lossSlotsSegmentMap?api.get(key)!}
                  </#list>
                  ]
                </font>
              </#if>
            <#elseif (appDesc.type == 5)>
              <button type="button" class="btn btn-primary" data-bs-target="#redisAddSentinelModal"
                      data-bs-toggle="modal">添加sentinel节点
              </button>
              <button type="button" class="btn btn-primary" data-bs-target="#redisSentinelFailOverModal"
                      data-bs-toggle="modal">FailOver
              </button>
              <button type="button" class="btn btn-primary" data-bs-target="#redisSentinelResetModal"
                      data-bs-toggle="modal">Reset
              </button>
            </#if>
            <#if (appDesc.type == 2)>
              <button type="button" id="configRestartId" class="btn btn-primary ml-3" data-bs-target="#configAndRestartModal"
                      data-bs-toggle="modal">config / restart
              </button>
            </#if>
          </h4>
        </div>
      </div>
  </div>
  <div class="col-12">
    <div class="card">
      <div class="card-body table-responsive">
        <table class="table table-bordered table-striped table-hover table-sm">
          <thead>
          <tr>
            <th>ID</th>
            <th>实例</th>
            <th>k8s容器</th>
            <th>实例状态</th>
            <th>角色</th>
            <th>主实例ID</th>
            <th>内存使用</th>
            <th>对象数</th>
            <th>连接数</th>
            <th>命中率</th>
            <th>碎片率</th>
            <th>日志</th>
            <th>节点运维</th>
            <th>故障转移</th>
          </tr>
          </thead>
          <tbody>
          <div hidden="hidden">
            <select style="display:none" id="instanceList">
              <#list instanceList as instance>
                <option value="${instance.id!}"/>
                <#if (instance.status == 1) && (instance.masterInstanceId == 0) && (instance.type != 5)>
                  <input name="selectOneMaster" hidden value="${instance.id!}"/>
                </#if>
              </#list>
              </optgroup>
            </select>
          </div>

          <#list instanceListMap?keys as key>
            <#list instanceListMap?api.get(key) as instance>
              <#assign instanceStatsMapKey = ((instance.ip) + ":" + (instance.port))>
              <tr>
                <td>
                  <a href="${request.contextPath}/admin/instance/index?instanceId=${instance.id!}" target="_blank">${instance.id!}</a>
                </td>
                <td>
                  <#if (k8sMachineMaps?api.get(instance.ip))??>
                    <a target="_blank" href="${request.contextPath}/manage/machine/pod/changelist?ip=${instance.ip!}"
                       title="查看pod变更记录">${instance.ip!}</a>:${instance.port!}
                  </#if>
                  <#if !((k8sMachineMaps?api.get(instance.ip))??)>
                    ${instance.ip!}:${instance.port!}
                  </#if>
                </td>
                <td>
                  <#if (k8sMachineMaps?api.get(instance.ip))??>
                    <a target="_blank" href="${request.contextPath}/manage/machine/pod/changelist?ip=${instance.ip!}"
                       title="查看pod变更记录">是</a>
                  </#if>
                  <#if !((k8sMachineMaps?api.get(instance.ip))??)>
                    否
                  </#if>
                </td>
                <td>
                  ${instance.statusDesc!}
                  <#if (instance.status==2) || (instance.status==3)>
                    <br/>
                    ${instance.updateTimeDesc!}
                  </#if>
                </td>
                <td>${instance.roleDesc!}</td>
                  <#if (instance.masterInstanceId >0)>
                    <td>
                      <a href="${request.contextPath}/admin/instance/index?instanceId=${instance.masterInstanceId!}"
                         target="_blank">${instance.masterInstanceId!}</a>
                    </td>
                  <#else>
                    <td></td>
                  </#if>
                <td>
                  <div class="progress progress-fs-1" role="progressbar"
                       aria-valuenow="${memUsePercentValue!}"
                       aria-valuemax="100"
                       aria-valuemin="0">
                    <#if instanceStatsMap?? && instanceStatsMap[instanceStatsMapKey]?? && ((instanceStatsMap[instanceStatsMapKey]).memUsePercent >= 80)>
                      <#assign progressBarStatus='bg-danger'>
                    <#else>
                      <#assign progressBarStatus='bg-success'>
                    </#if>
                    <#if instanceStatsMap?? && instanceStatsMap[instanceStatsMapKey]??>
                      <#assign memUsePercentValue = ((instanceStatsMap[instanceStatsMapKey]).memUsePercent!)>
                    <#else>
                      <#assign memUsePercentValue='0'>
                    </#if>
                    <div class="progress-bar ${progressBarStatus!}"
                         style="width: ${memUsePercentValue!}%; overflow: visible;">
                      <span style="color: #000000; margin-bottom: 0">
                        <#if instanceStatsMap?? && instanceStatsMap[instanceStatsMapKey]??>
                          ${((instanceStatsMap[instanceStatsMapKey]).usedMemory / 1024 / 1024 / 1024)?string('#.##')} G&nbsp;&nbsp;Used
                            /${(instance.mem / 1024)?string('#.##')}G&nbsp;&nbsp;Total
                        </#if>
                      </span>
                    </div>
                  </div>
                </td>
                <td>
                  <#if (instanceStatsMap[instanceStatsMapKey])??>
                    ${(instanceStatsMap[instanceStatsMapKey]).currItems!}
                  </#if>
                </td>
                <td>
                  <a href="${request.contextPath}/admin/instance/index?instanceId=${instance.id!}&tabTag=instance_clientList"
                     target="_blank">
                    <#if (instanceStatsMap[instanceStatsMapKey])??>
                      ${(instanceStatsMap[instanceStatsMapKey]).currConnections!}
                    </#if>
                  </a>
                </td>
                <td>
                  <#if (instanceStatsMap[instanceStatsMapKey])??>
                    ${(instanceStatsMap[instanceStatsMapKey]).hitPercent!}
                  </#if>
                </td>
                <td>
                  <#if instanceStatsMap?? && (instanceStatsMap[instanceStatsMapKey])??>
                    <#assign memFragmentationRatio=(instanceStatsMap[instanceStatsMapKey]).memFragmentationRatio>
                  <#else>
                    <#assign memFragmentationRatio=0>
                  </#if>
                  <#if (memFragmentationRatio > 5) && ((instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100)>
                    <#assign memFragmentationRatioLabel='bg-danger'>
                  <#elseif (memFragmentationRatio >= 3) && (memFragmentationRatio < 5) && ((instanceStatsMap[instanceStatsMapKey]).usedMemory > 1024 * 1024 * 100)>
                    <#assign memFragmentationRatioLabel='bg-warning'>
                  <#else>
                    <#assign memFragmentationRatioLabel='bg-success'>
                  </#if>
                  <label class="${memFragmentationRatioLabel!} rounded">&nbsp;${memFragmentationRatio!}&nbsp;</label>
                </td>
                <td>
                  <a target="_blank" href="${request.contextPath}/manage/instance/log?instanceId=${instance.id!}">查看</a>
                </td>
                <td style="white-space: nowrap">
                  <div>
                    <#if (instance.status ==2)>
                      <button type="button" class="btn btn-sm btn-success mb-2"
                              onclick="startInstance('${appDesc.appId!}','${instance.id!}')">
                        启动实例
                      </button>
                      <#if (instance.type ==2)>
                        <br>
                        <button type="button" class="btn btn-sm btn-danger mb-2"
                                onclick="forgetInstance('${appDesc.appId!}','${instance.id!}')">
                          永久下线
                        </button>
                      </#if>
                    <#elseif (instance.status ==0)>
                      <button type="button" class="btn btn-sm btn-success mb-2"
                              onclick="startInstance('${appDesc.appId!}','${instance.id!}')">
                        启动实例
                      </button>
                      <br>

                      <button type="button" class="btn btn-sm btn-warning mb-2"
                              onclick="shutdownInstance('${appDesc.appId!}','${instance.id!}')">
                        下线实例
                      </button>
                      <#if (instance.masterInstanceId == 0) && (appDesc.type == 2) && (lossSlotsSegmentMap[instanceStatsMapKey]??) && (lossSlotsSegmentMap[instanceStatsMapKey] != '')>
                          <br>
                          <button type="button" class="btn btn-sm btn-primary mb-2"
                                  data-bs-target="#redisAddFailSlotsMasterModal${instance.id!}"
                                  data-bs-toggle="modal">修复slot丢失数据
                          </button>
                      </#if>
                    <#elseif (instance.status == -1)>
                      <button type="button" class="btn btn-sm btn-success mb-2"
                              onclick="startInstance('${appDesc.appId!}','${instance.id!}')">
                        启动实例
                      </button>
                      <br>
                      <button type="button" class="btn btn-sm btn-warning mb-2"
                              onclick="shutdownInstance('${appDesc.appId!}','${instance.id!}')">
                        下线实例
                      </button>
                    <#elseif (instance.status == 1)>
                      <button type="button" class="btn btn-sm btn-warning mb-2"
                              onclick="shutdownInstance('${appDesc.appId!}', '${instance.id!}')">
                        下线实例
                      </button>
                      <br>
                      <button type="button" class="btn btn-sm btn-info mb-2"
                              data-bs-target="#instanceAddConfigModal_${instance.id!}"
                              data-bs-toggle="modal">修改配置
                      </button>
                      <#if (instance.masterInstanceId == 0) && (instance.type != 5)>
                        <br>
                        <button type="button" class="btn btn-sm btn-primary mb-2"
                                data-bs-target="#redisClusterAddSlaveModal_${instance.id!}"
                                data-bs-toggle="modal">添加Slave
                        </button>
                      </#if>
                    </#if>
                  </div>
                </td>
                <td>
                  <div>
                    <#if (instance.status == 1)>
                      <#if (instance.masterInstanceId > 0) && (instance.type == 2)>
                        <button type="button" class="btn btn-sm btn-success mb-2"
                                data-bs-target="#redisClusterFailOverManualModal${instance.id!}"
                                data-bs-toggle="modal">Manual
                        </button>
                        <br>
                        <button type="button" class="btn btn-sm btn-primary mb-2"
                                data-bs-target="#redisClusterFailOverForceModal${instance.id!}"
                                data-bs-toggle="modal">Force
                        </button>
                        <br>
                        <button type="button" class="btn btn-sm btn-danger"
                                data-bs-target="#redisClusterFailOverTakeOverModal${instance.id!}"
                                data-bs-toggle="modal">TakeOver
                        </button>
                      </#if>
                    </#if>
                  </div>
                </td>
              </tr>
            </#list>
            <tr style="height: 10px"></tr>
          </#list>
          </tbody>
        </table>
      </div>
  </div>
</div>

<div id="redisAddSentinelModal" class="modal fade" tabindex="-1" data-width="400">
  <div class="modal-dialog">
    <div class="modal-content">

      <div class="modal-header">
        <h4 class="modal-title">添加sentinel节点</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
      </div>

      <form class="form-horizontal form-bordered form-row-stripped">
        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="col-md-12">
              <!-- form-body开始 -->
              <div class="form-body">
                <div class="form-group row">
                  <label class="control-label col-md-3">sentinel节点Ip:</label>
                  <div class="col-md-7">
                    <input type="text" name="sentinelIp" id="sentinelIp" placeholder="sentinel节点Ip"
                           class="form-control">
                  </div>
                </div>
              </div>
              <!-- form-body 结束 -->
              <div id="redisAddSentinelInfo"></div>
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
          <button type="button" id="redisAddSentinelBtn" class="btn btn-danger"
                  onclick="redisAddSentinel('${appDesc.appId!}')">Ok
          </button>
        </div>
      </form>
    </div>
  </div>
</div>


<div id="redisSentinelFailOverModal" class="modal fade" tabindex="-1" data-width="400">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">redis-Sentinel从节点FailOver操作</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
      </div>

      <div class="modal-body">
        <div class="row">
          <!-- 控件开始 -->
          <div class="container">
            <div class="col-md-12">
              <div>你确定执行failOver操作?</div>
              <div id="redisSentinelFailOverInfo"></div>
            </div>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
        <button type="button" id="redisSentinelFailOverBtn" class="btn btn-danger"
                onclick="redisSentinelFailOver('${appDesc.appId!}')">Ok
        </button>
      </div>
    </div>
  </div>
</div>

<div id="redisSentinelResetModal" class="modal fade" tabindex="-1" data-width="400">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <h4 class="modal-title">redis-Sentinel Reset操作</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
      </div>

      <div class="modal-body">
        <div class="row">
          <!-- 控件开始 -->
          <div class="container">
            <div class="col-md-12">
              <div>你确定重置sentinel实例状态?</div>
              <div id="redisSentinelResetInfo"></div>
            </div>
          </div>
        </div>
      </div>

      <div class="modal-footer">
        <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
        <button type="button" id="redisSentinelResetBtn" class="btn btn-danger"
                onclick="redisSentinelReset('${appDesc.appId!}')">Ok
        </button>
      </div>
    </div>
  </div>
</div>

<input type="hidden" id="appId" value="${appDesc.appId!}">

<#list instanceList as instance>
  <div id="redisClusterFailOverManualModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Redis-Cluster从节点FailOver Manual操作</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="container">
              <div class="col-md-12">
                <div>你确定对实例${instance.id!}执行FailOver Manual操作?</div>
                <div id="redisClusterFailOverManualInfo${instance.id!}"></div>
              </div>
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
          <button type="button" id="redisClusterFailOverManualBtn${instance.id!}" class="btn btn-danger"
                  onclick="redisClusterFailOverManual('${appDesc.appId!}', '${instance.id!}')">Ok
          </button>
        </div>
      </div>
    </div>
  </div>

  <div id="redisClusterFailOverForceModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Redis-Cluster从节点FailOver Force操作</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="container">
              <div class="col-md-12">
                <div>你确定对实例${instance.id!}执行FailOver Force操作?</div>
                <div id="redisClusterFailOverForceInfo${instance.id!}"></div>
              </div>
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
          <button type="button" id="redisClusterFailOverForceBtn${instance.id!}" class="btn btn-danger"
                  onclick="redisClusterFailOverForce('${appDesc.appId!}', '${instance.id!}')">Ok
          </button>
        </div>
      </div>
    </div>
  </div>


  <div id="redisClusterFailOverTakeOverModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Redis-Cluster从节点FailOver TakeOver操作</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="container">
              <div class="col-md-12">
                <div>你确定对实例${instance.id!}执行FailOver TakeOver操作?</div>
                <div id="redisClusterFailOverTakeOverInfo${instance.id!}"></div>
              </div>
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
          <button type="button" id="redisClusterFailOverTakeOverBtn${instance.id!}" class="btn btn-danger"
                  onclick="redisClusterFailOverTakeOver('${appDesc.appId!}', '${instance.id!}')">Ok
          </button>
        </div>
      </div>
    </div>
  </div>


  <div id="redisClusterDelNodeModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title">Redis-Cluster节点删除操作</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <div class="modal-body">
          <div class="row">
            <div class="container">
              <div class="col-md-12">
                <div>你确定对实例${instance.id!}执行删除操作?</div>
                <div id="redisClusterDelNodeInfo${instance.id!}"></div>
              </div>
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
          <button type="button" id="redisClusterDelNodeBtn${instance.id!}" class="btn btn-danger"
                  onclick="redisClusterDelNode('${appDesc.appId!}', '${instance.id!}')">Ok
          </button>
        </div>
      </div>
    </div>
  </div>


  <div id="instanceAddConfigModal_${instance.id!}" name="addConfig-modal" class="modal fade" tabindex="-1"
       data-width="400"
       aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">

        <div class="modal-header">
          <h4 class="modal-title">
            更新配置
            <h5>【实例】${instance.ip!}:${instance.port!}</h5>
          </h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <form class="form-horizontal form-bordered form-row-stripped">
          <div class="modal-body">
            <div class="row">
              <!-- 控件开始 -->
              <div class="col-md-12">
                <!-- form-body开始 -->
                <div class="form-body">
                  <div class="form-group row">
                    <label class="control-label col-md-3">配置项:</label>
                    <div class="col-md-8">
                      <select id="appConfigKey${instance.id!}" name="appConfigKey"
                              class="selectpicker border rounded w-100"
                              data-live-search="true" title="选择配置项" data-width="30%"
                              data-size="8">
                      </select>
                    </div>
                  </div>

                  <div class="form-group row">
                    <div class="col-md-8 offset-md-3">
                      <input type="text" id="newConfigKey${instance.id!}" class="form-control"
                             placeholder="新增配置项"/>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="control-label col-md-3">配置值:</label>
                    <div class="col-md-8">
                      <input type="text" name="appConfigValue" id="appConfigValue${instance.id!}"
                             value="${appConfigValue!}" class="form-control">
                    </div>
                  </div>
                </div>
                <!-- form-body 结束 -->
              </div>
            </div>
          </div>

          <div class="modal-footer">
            <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
            <button type="button" id="instanceAddConfigBtn${instance.id!}" class="btn btn-danger"
                    onclick="addConfigInstance('${appDesc.appId!}', '${instance.id!}','${instance.ip!}','${instance.port!}')">
              Ok
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>

  <div id="redisClusterAddSlaveModal_${instance.id!}" name="addSlave-modal" class="modal fade" tabindex="-1"
       data-width="400"
       aria-hidden="true">
    <div class="modal-dialog">
      <div class="modal-content">

        <div class="modal-header">
          <h4 class="modal-title">添加slave节点</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <h5>主节点信息：</h5>
        <#if !(machineMap[instance.ip]??) || !(machineMap[instance.ip].info.realIp??)>
          <#assign realIp = "无">
        <#else>
          <#assign realIp = machineMap[instance.ip].info.realIp!>
        </#if>
        <#if !(machineMap[instance.ip]??) || !(machineMap[instance.ip].info.rack??)>
          <#assign rack = "无">
        <#else>
          <#assign rack = machineMap[instance.ip].info.rack!>
        </#if>
        <h6>【ID】${instance.id!} 【实例】${instance.ip!}:${instance.port!}
          【宿主机-机架】${realIp!}-${rack!}</h6>

        <form class="form-horizontal form-bordered form-row-stripped">
          <div class="modal-body">
            <div class="row">
              <!-- 控件开始 -->
              <div class="col-md-12">
                <!-- form-body开始 -->
                <div class="form-body">
                  <div class="form-group row">
                    <label class="col-form-label col-auto">slave节点:</label>
                    <div class="col-md-6" id="div_slaveIp${instance.id!}">
                      <select id="slaveIp${instance.id!}" name="slaveIp"
                              class="selectpicker border rounded w-100" data-live-search="true">
                      </select>
                    </div>
                    <button type="button" class="btn btn-success btn-sm col-auto offset-md-1"
                            onclick="genSlaveIp('${appDesc.appId!}', '${instance.id!}')">自动生成
                    </button>
                    <br/><br/>
                    <p id="genSlaveIpNote${instance.id!}" class="col-md-8 offset-md-3"
                       style="color: red; display: none">
                      <i class="ace-icon bi bi-exclamation-triangle bigger-120"></i>&nbsp;&nbsp;&nbsp;自动生成slave节点ip失败
                    </p>
                  </div>
                </div>
                <!-- form-body 结束 -->
                <div id="redisClusterAddSlaveInfo${instance.id!}"></div>
              </div>
            </div>
          </div>

          <div class="modal-footer">
            <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
            <button type="button" id="redisClusterAddSlaveBtn${instance.id!}" class="btn btn-danger"
                    onclick="redisClusterAddSlave('${appDesc.appId!}', '${instance.id!}')">Ok
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>

  <div id="redisSentinelAddSlaveModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">

        <div class="modal-header">
          <h4 class="modal-title">添加slave节点(主节点:${instance.id!}, ${instance.ip!}:${instance.port!})</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <form class="form-horizontal form-bordered form-row-stripped">
          <div class="modal-body">
            <div class="row">
              <!-- 控件开始 -->
              <div class="col-md-12">
                <!-- form-body开始 -->
                <div class="form-body">
                  <div class="form-group row">
                    <label class="col-form-label col-md-3">Slave节点Ip:</label>
                    <div class="col-md-7">
                      <input type="text" name="sentinelSlaveIp" id="sentinelSlaveIp${instance.id!}"
                             placeholder="Slave节点Ip" class="form-control">
                    </div>
                  </div>
                </div>
                <!-- form-body 结束 -->
                <div id="redisSentinelAddSlaveInfo${instance.id!}"></div>
              </div>
            </div>
          </div>

          <div class="modal-footer">
            <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
            <button type="button" id="redisSentinelAddSlaveBtn${instance.id!}" class="btn btn-danger"
                    onclick="redisSentinelAddSlave('${appDesc.appId!}', '${instance.id!}')">Ok
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>

  <div id="redisAddFailSlotsMasterModal${instance.id!}" class="modal fade" tabindex="-1" data-width="400">
    <div class="modal-dialog">
      <div class="modal-content">

        <div class="modal-header">
          <h4 class="modal-title">修复failslots</h4>
          <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
        </div>

        <form class="form-horizontal form-bordered form-row-stripped">
          <div class="modal-body">
            <div class="row">
              <!-- 控件开始 -->
              <div class="col-md-12">
                <!-- form-body开始 -->
                <div class="form-body">
                  <div class="form-group row">
                    <label class="col-form-label col-md-3">节点Ip:</label>
                    <div class="col-md-7">
                      <input type="text" name="failSlotsMasterHost"
                             id="failSlotsMasterHost${instance.id!}"
                             placeholder="failSlotsMasterHost" class="form-control">
                    </div>
                  </div>
                </div>
                <!-- form-body 结束 -->
                <div id="redisAddFailSlotsMasterInfo${instance.id!}"></div>
              </div>
            </div>
          </div>

          <div class="modal-footer">
            <button type="button" data-bs-dismiss="modal" class="btn btn-secondary">Close</button>
            <button type="button" id="redisAddFailSlotsMasterBtn${instance.id!}" class="btn btn-danger"
                    onclick="redisAddFailSlotsMaster('${appDesc.appId!}', '${instance.id!}')">Ok
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>
</#list>


<select id="slaveIp" name="slaveIp" hidden="hidden">
  <option value="-1">请选择slave</option>
  <#list machineMap?keys as key>
    <#assign machine = machineMap?api.get(key)>
    <#if machineInstanceCountMap?? && (machineInstanceCountMap[machine.info.ip]??)>
      <#assign usedCpu = machineInstanceCountMap[machine.info.ip]?string("0")>
    <#else>
      <#assign usedCpu = "0">
    </#if>
    <#assign cpu = (machine.info.cpu)?string("0")>
    <#assign cpuUsage = ((usedCpu?number)/(cpu?number)*100)?string("0")>
    <#assign usedMemRss = ((machine.machineMemInfo.usedMemRss?number)/1024/1024/1024)?string("0.0")>
    <#assign mem = (machine.info.mem)?string("0.0")>
    <#assign memUsage = ((usedMemRss?number)/(mem?number)*100)?string("0")>
    <#assign realIp = machine.info.realIp!>
    <#assign rack = machine.info.rack!>
    <#assign disk = machine.info.disk?string("0.0")>
    <#if machine.diskUsageRatio?? && machine.diskTotal??>
      <#assign diskUsageRatio = machine.diskUsageRatio>
      <#assign diskUsage = (((machine.diskTotal?number)/1024 - (machine.diskAvailable?number)/1024)?string("0"))>
    <#else>
      <#assign diskUsageRatio = '0'>
      <#assign diskUsage = '0'>
    </#if>
    <#if machine.info.realIp?? && (machine.info.realIp=='')><#assign realIp ="无realIp"></#if>
    <#if machine.info.rack?? && (machine.info.rack=='')><#assign rack ="无rack"></#if>
    <#if (machine.info.useType==0)>
      <#assign extraDesc ="专用-" + machine.info.extraDesc>
    <#elseif (machine.info.useType==1)>
      <#assign extraDesc = "测试-" + machine.info.extraDesc>
    <#elseif (machine.info.useType==2)>
      <#assign extraDesc = "混合-" + machine.info.extraDesc>
    <#else>
      <#assign extraDesc = "" + machine.info.extraDesc>
    </#if>
    <#if (appDesc.type == 12) && (machine.info.type == 6)>
      <option value="${machine.ip!}">${machine.ip!}：【${usedCpu!}/${cpu!}核(${cpuUsage!}%)】【${usedMemRss!}/${mem!}G(${memUsage!}%)】【${diskUsage!}/${disk!}G(${diskUsageRatio!}%)】【${realIp!}-${rack!}】【${extraDesc!}】</option>
    <#elseif ((appDesc.type == 2) || (appDesc.type == 5) || (appDesc.type == 6)) && (machine.info.type == 0)>
      <option value="${machine.ip!}">${machine.ip!}：【${usedCpu!}/${cpu!}核(${cpuUsage!}%)】【${usedMemRss!}/${mem!}G(${memUsage!}%)】【${diskUsage!}/${disk!}G(${diskUsageRatio!}%)】【${realIp!}-${rack!}】【${extraDesc!}】</option>
    </#if>
  </#list>
</select>

<div id="configAndRestartModal" name="configAndRestart-modal" class="modal fade" tabindex="-1"
     data-width="400"
     aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">

      <div class="modal-header">
        <h4 class="modal-title">修改配置/滚动重启</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
      </div>
      <div class="d-block">
        <h5>【应用】${appDesc.appId!}:${appDesc.name!}</h5>
        <button class="btn btn-warning btn-sm" style="float: right;" onclick="openRestartRecord('${appDesc.appId!}')">
          查看重启进程记录
        </button>
      </div>

      <form class="form-horizontal form-bordered form-row-stripped">
        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="col-md-12">
              <!-- form-body开始 -->
              <div class="form-body">
                <div class="form-group row">
                  <label class="control-label col-md-3">
                    操作类型:
                  </label>
                  <div class="col-md-8">
                    <label class="radio-inline">
                      <input type="hidden" id="recordId" name="recordId" class="form-control"/>
                      <input type="radio" name="isUpdateConfig" value="0" onchange="moduleSelect('0')" checked="checked"> 滚动重启
                      <span class="glyphicon glyphicon-question-sign" data-bs-toggle="tooltip"
                            data-placement="right" title="按照主从分组后重启">
                                            </span>
                    </label>
                    <label>
                    </label>
                    <label>&nbsp;&nbsp;</label>
                    <label class="radio-inline">
                      <input type="radio" name="isUpdateConfig" value="1" onchange="moduleSelect('1')"> 修改配置
                      <span class="glyphicon glyphicon-question-sign" data-bs-toggle="tooltip"
                            data-placement="right" title="某些配置修改后，需要重启实例">
                                            </span>
                    </label>
                  </div>
                </div>

                <div id="moduleInfo" style="display: none">

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">配置项列表:</label>
                    <div class="col-md-8">
                      <select id="configListId" name="appConfigKey"
                              class="selectpicker rounded border w-100"
                              data-live-search="true" title="选择配置项" data-width="31%"
                              data-size="8" onchange="setSelectedConfig()">
                      </select>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">修改配置项:</label>
                    <div class="col-md-8">
                      <input type="text" id="configName" name="configName" class="form-control"
                             placeholder="参考配置项列表"/>
                    </div>
                  </div>

                  <ul id="configRowGroup">
                    <span id="configValueTip" style="color: orange">* 请确认配置值是否需分开</span>
                    <li name="configRow">
                      <div class="form-group row">
                        <label class="col-form-label col-md-3">配置值:</label>
                        <div class="col-md-8">
                          <input type="text" name="configValue" class="form-control"
                                 placeholder="如同一配置项有多个配置值，请分开填写"/>
                        </div>
                      </div>
                    </li>
                  </ul>

                  <div class="form-group row">
                    <div class="col-md-1 offset-md-9">
                      <button id="addConfigRowBtn" type="button" onclick="addConfigRow()">+</button>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">
                      选择实例<font color='red'>(*)</font>:
                    </label>
                    <div class="col-md-8">
                      <select id="configInstanceList" name="configInstance" class="selectpicker border rounded w-100" multiple data-live-search="true" data-width="31%">
                        <option value="0">所有实例</option>
                        <#list instanceList as instanceInfo>
                          <#if (instanceInfo.status == 1) && ((instanceInfo.type == 2) || (instanceInfo.type == 6))>
                            <option value="${instanceInfo.id!}">${instanceInfo.ip!}:${instanceInfo.port!}</option>
                          </#if>
                        </#list>
                      </select>
                    </div>
                  </div>
                </div>

                <div class="form-group row">
                  <label class="col-form-label col-md-3">
                    是否允许主从切换:
                  </label>
                  <div class="col-md-8">
                    <select id="msTransferFlag" name="msTransferFlag" class="form-select">
                      <option value="0" selected>
                        否
                      </option>
                      <option value="1">
                        是
                      </option>
                    </select>
                    <span class="help-block">
                                            当滚动重启和修改配置需重启时，是否允许原有的主节点切换为从节点
                                        </span>
                  </div>
                </div>

                <div class="form-group row">
                  <label class="col-form-label col-md-3">
                    是否快速重启:
                  </label>
                  <div class="col-md-8">
                    <select id="msQuickFinishFlag" name="msQuickFinishFlag" class="form-select">
                      <option value="0" selected>
                        否
                      </option>
                      <option value="1">
                        是
                      </option>
                    </select>
                    <span class="help-block">
                                              当滚动重启和修改配置需重启时，是否快速重启(不考虑客户端集群拓扑耗时)
                                          </span>
                  </div>
                </div>


              </div>

              <!-- form-body 结束 -->
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" id="configAndRestartCloseBtn" class="btn btn-secondary" onclick="configAndRestartClose('${appDesc.appId!}')">Close</button>
          <button type="button" id="configAndRestartBtn" class="btn btn-danger"
                  onclick="configAndRestart('${appDesc.appId!}')">
            Ok
          </button>
          <button type="button" id="restartAfterConfigBtn" class="btn btn-danger"
                  onclick="restart('${appDesc.appId!}')" style="display: none">
            Restart to active config
          </button>
        </div>
      </form>
    </div>
  </div>
</div>


<div id="configCommandModal" name="configCommand-modal" class="modal fade" tabindex="-1"
     data-width="400"
     aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">

      <div class="modal-header">
        <h4 class="modal-title">修改命令（改名/映射）</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-hidden="true"></button>
      </div>
      <div class="d-block">
        <h5>【应用】${appDesc.appId!}:${appDesc.name!}</h5>
        <button class="btn btn-warning btn-sm" style="float: right;" onclick="openRestartRecord('${appDesc.appId!}')">
          查看重启进程记录
        </button>
      </div>

      <form class="form-horizontal form-bordered form-row-stripped">
        <div class="modal-body">
          <div class="row">
            <!-- 控件开始 -->
            <div class="col-md-12">
              <!-- form-body开始 -->
              <div class="form-body">
                <div class="form-group row">
                  <label class="control-label col-md-3">
                    操作类型:
                  </label>
                  <div class="col-md-8">
                    <label class="radio-inline">
                      <input type="radio" name="isRenameCommand" value="0" checked="checked"> 命令重命名
                      <!--<span class="glyphicon glyphicon-question-sign" data-bs-toggle="tooltip"
                            data-placement="right" title="按照主从分组后重启">
                                            </span>-->
                    </label>
                    <label>
                    </label>
                    <!--<label>&nbsp;&nbsp;</label>
                    <label class="radio-inline">
                      <input type="radio" name="isMappingCommand" value="1" onchange="moduleSelect('1')"> 命令映射
                      <span class="glyphicon glyphicon-question-sign" data-bs-toggle="tooltip"
                            data-placement="right" title="某些配置修改后，需要重启实例">
                                            </span>
                    </label>-->
                  </div>
                </div>

                <div id="commandInfo">

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">命令列表:</label>
                    <div class="col-md-8">
                      <select id="cmdListId"
                              class="selectpicker rounded border w-100" multiple
                              data-live-search="true" title="选择命令" data-width="31%"
                              data-size="8" onchange="setSelectedRenameCmd()">
                      </select>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">已改名命令:</label>
                    <div class="col-md-8">
                      <textarea rows="5" id="existCommandName" name="existCommandName" class="form-control"
                                disabled="disabled"></textarea>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">待改名命令:</label>
                    <div class="col-md-8">
                      <textarea rows="5" id="commandName" name="commandName" class="form-control"></textarea>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">改名命令-后缀:</label>
                    <div class="col-md-8">
                      <input type="text" id="commandSuffix" name="commandSuffix" class="form-control" value="_dep"
                             placeholder="添加到命令尾部"/>
                    </div>
                  </div>

                  <div class="form-group row">
                    <label class="col-form-label col-md-3">
                      选择实例<font color='red'>(*)</font>:
                    </label>
                    <div class="col-md-8">
                      <select id="cmdInstanceList" name="configInstance" class="selectpicker border rounded w-100" multiple data-live-search="true" data-width="31%">
                        <option value="0">所有实例</option>
                        <#list instanceList as instanceInfo>
                        <#if (instanceInfo.status == 1) && ((instanceInfo.type == 2) || (instanceInfo.type == 6))>
                        <option value="${instanceInfo.id!}">${instanceInfo.ip!}:${instanceInfo.port!}</option>
                        </#if>
                      </#list>
                      </select>
                    </div>
                  </div>
                </div>
              </div>
            <!-- form-body 结束 -->
            </div>
          </div>
        </div>

        <div class="modal-footer">
          <button type="button" id="configCommandCloseBtn" class="btn btn-secondary" onclick="configCommandClose('${appDesc.appId!}')">Close</button>
          <button type="button" id="configCommandBtn" class="btn btn-danger"
                  onclick="configCommand('${appDesc.appId!}')">
            Ok
          </button>
        </div>
      </form>
    </div>
  </div>
</div>